import 'dart:math';
import 'package:eshi/app/shi/data/HistoryMark.dart';
import 'package:eshi/app/shi/taxis/TabEditPage.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

//模拟事件 
class Event_KeyDown extends RawKeyDownEvent{
  Event_KeyDown({required LogicalKeyboardKey logicalKey, required PhysicalKeyboardKey physicalKey, List<ModifierKey>? modifiers}) 
    : super(data:KeyEventData(logical:logicalKey,physical:physicalKey,modifiers:modifiers));

  @override
  get isShiftPressed => data.isShiftPressed;
  @override
  get isControlPressed => data.isControlPressed;
}
class KeyEventData extends RawKeyEventData{
  LogicalKeyboardKey logical;
  PhysicalKeyboardKey physical;
  List<ModifierKey>? modifiers;
  KeyEventData({required this.logical, required this.physical, this.modifiers});
  @override
  KeyboardSide? getModifierSide(ModifierKey key) {
    // TODO: implement getModifierSide
    return null;
  }

  @override
  bool isModifierPressed(ModifierKey key, {KeyboardSide side = KeyboardSide.any}) {
    // TODO: implement isModifierPressed
    if(modifiers==null) return false;
    return modifiers!.contains(key);
  }

  @override
  // TODO: implement keyLabel
  String get keyLabel => logical.keyLabel;

  @override
  // TODO: implement logicalKey
  LogicalKeyboardKey get logicalKey => logical;

  @override
  // TODO: implement physicalKey
  PhysicalKeyboardKey get physicalKey => physical;
}


//数据
class CodeBlock{
    int startLine;
    int endLine;
    String code;
    int startPos;
    int endPos;
    String befor;
    String after;
    CodeBlock({required this.startLine,required this.endLine,required this.code,
      required this.befor,required this.endPos,required this.after,required this.startPos});
    int get lineCount => endLine - startLine;
    String get body => befor+code+after;
    int get beforSpaceSize => befor.replaceFirst(RegExp(r"\S+"),"").length;
    int get startLinePos => startPos-befor.length;
    int get endLinePos => endPos+after.length;
}

mixin  TabEditPageAction on State<TabEditPage>{
  TabEditPageState get self => this as TabEditPageState;
  close(){
    Navigator.pop(context);    
  }
  addMark(String type,String name){
    if(!self.marksGroup.containsKey(type)) self.marksGroup[type]= [];
    self.marksGroup[type]?.add(name);
    //显示更新 
    setState(() {
      if(!widget.marks!.containsKey(type)) widget.marks![type]= [];
      widget.marks![type]!.add(name);  
    });
    //页面没有的话添加文件到页面 
    if(!_data.contains(name)){
      var pos = _pos;
      var newText = _data;
      newText = "${newText.substring(0,pos)+name} ${newText.substring(pos)}";
      pos +=name.length+1;
      var selection = TextSelection(baseOffset: pos,extentOffset:pos);
       // 更新文本和光标位置
      self.controller.value = TextEditingValue(
        text: newText,
        selection: selection,
      );
    }
  }
  //连接按钮长安实现 连接的自动新增 百度百科的新增是个问题 怎么词语拆分呢？  
  void marksAdds(String doc) {
    List<String> haveKey = [];
    widget.marks?.forEach((k,v) => haveKey.addAll(v));
    self.marksGroup.forEach((k,v) => haveKey.addAll(v));
    HistoryMark(doc,(type,name){
      if(!haveKey.contains(name)){
        addMark(type, name);
      }
    });
  }
  get renderBox =>  self.textFieldKey.currentContext?.findRenderObject() as RenderBox?;
  double get docBoxWidth => renderBox!=null && renderBox.size!=null ? renderBox.size.width-30 : 600;
  int _getLineWrapCount(String line){
     //使用TextPainter计算文本布局
    final textPainter = TextPainter(
      text: TextSpan(text: line, style: widget.textStyle),
      maxLines: null, // 不限制行数（允许自动换行）
      textDirection: TextDirection.ltr,
    )..layout(maxWidth: docBoxWidth); // 限制最大宽度为TextField可用宽度
    return textPainter.computeLineMetrics().length;
  }
  //行自动折行的数量 只保存自动折行的行 
  var docLinesCountMap={};
  //文本的行内容缓存
  var _docLines=[];
  var _docLinesUpBeforTime;
  var _docSize=0;
  var _docMaxLineSize = 0;
  double? get fontSize => self.widget.textStyle!.fontSize;
  get maxLineWidth => max(_docMaxLineSize*(fontSize??14) ,500);
  get docLines{
    if(_docLines.isEmpty || timeStamp.inMilliseconds - _docLinesUpBeforTime > 5000){
      final text = self.controller.text;
      _docLines = text.split('\n');
      _docLinesUpBeforTime = timeStamp.inMilliseconds;
    }
    return _docLines;
  }
   // 更新行号计数
  void updateLineNumbers() async{
    final text = self.controller.text;
    // 计算换行符数量
    var newLineCount = docLines.length;

    //自动折行的行数 
    if(self.isWrapText){
        int wrapSize = (docBoxWidth/14).toInt();
        for(var i=0;i<docLines.length;i++){
          var line=docLines[i];
          if(line.length > wrapSize){
            final lineCount = _getLineWrapCount(line);
            if(lineCount>1) {
              docLinesCountMap[i] = lineCount;
            }
          }
        }
    }
    // 最后一行非空时额外加一行
    if (text.isNotEmpty && !text.endsWith('\n')) {
      newLineCount++;
    }

    if(text.length!=_docSize){
      _docSize =text.length;
      var maxLineSize = 0;
      docLines.forEach((line)=> maxLineSize = max(maxLineSize,line.length));
      if(maxLineSize != _docMaxLineSize){
        setState(() {
          _docMaxLineSize  = maxLineSize;
        });
      }
    }
    //选中行 
    final selection=self.controller.selection;
    final cursorOffset = selection.baseOffset;
    if(cursorOffset>-1){
      final beforLines = text.substring(0,cursorOffset).split("\n");
      final newCursorLine = beforLines.length-1;
      self.cursorCol = beforLines.last.length;
      self.cursorLevel = ((beforLines.last.length - beforLines.last.trimLeft().length) / widget.tabSpaces).toInt();
      if(self.cursorLine!=newCursorLine || selection.extentOffset != selection.baseOffset){
        self.cursorLine = newCursorLine;
        var cursorLines = [newCursorLine];
        if((selection.extentOffset - selection.baseOffset).abs()>0){
          cursorLines =  List.generate(selectionBlock.lineCount,(index)=>selectionBlock.startLine+index-1);
        }
        setState(() => self.cursorLines = cursorLines  );
      }
    }
    // 刷新行号
    if (newLineCount != self.lineCount) {
      setState(() => self.lineCount = newLineCount);
    }
    setState(() {});
  }
// 处理Tab键输入，转换为空格
  void handleInput(String addText) {
    final text = self.controller.text;
    final selection = self.controller.selection;
    
    // 在光标位置插入指定数量的空格
    final newText = text.substring(0, selection.start) + 
                   addText+ 
                  text.substring(selection.end);
    
    // 更新文本和光标位置
    self.controller.value = TextEditingValue(
      text: newText,
      selection: TextSelection.collapsed(
        offset: selection.start + addText.length,
      ),
    );
  }

  CodeBlock? _codeBlock;
  CodeBlock get selectionBlock{
     final selection =  self.controller.selection;
     final start = min(selection.baseOffset,selection.extentOffset);
     final end = max(selection.baseOffset,selection.extentOffset);
     if(_codeBlock!=null && _codeBlock!.startPos == start && _codeBlock!.endPos==end) return _codeBlock!;
     final text = self.controller.text;
     final codeBlock = text.substring(start,end);
     final a = text.substring(0,start).split("\n");
     final b = codeBlock.split("\n");
     final c = text.substring(end).split("\n");

    _codeBlock=CodeBlock(code:codeBlock, startLine:a.length, endLine:a.length+b.length, 
        startPos:start, endPos:end, befor:a.last,  after:c.first);
    return _codeBlock!;
  }
  void _upSelectionBlock(String body,int selectBeforChange){
    final text = self.controller.text;
    // 在光标位置插入指定数量的空格
    final newText = text.substring(0, selectionBlock.startLinePos) + 
                  body+
                  text.substring(selectionBlock.endLinePos);
    
    final int selectionStart = selectionBlock.startPos + selectBeforChange;
    // 更新文本和光标位置
    self.controller.value = TextEditingValue(
      text: newText,
      selection: TextSelection(
        baseOffset:  selectionStart,
        extentOffset: selectionStart+body.length-(selectionBlock.after.length + selectionBlock.befor.length+selectBeforChange)
      ),
    );
  }
  void linesTabSet(bool isAdd){
    final body  = selectionBlock.body.split("\n").map((line){
        if(isAdd) {
          return  ' ' * widget.tabSpaces+line;
        }else{ 
          if(line.startsWith(" ")){
            return line.substring(min(widget.tabSpaces,selectionBlock.beforSpaceSize));
          }
          return line;
        }
    }).join("\n");
    final int selectBeforChange = isAdd ? 8 : max(-8,0-selectionBlock.beforSpaceSize);
    _upSelectionBlock(body,selectBeforChange);
  }

  void linesCommentSet(){
      var rows = selectionBlock.body.split("\n");
      var isAdd = rows.any((line)=> !line.startsWith("//"));
      final body  = rows.map((line){
          return (isAdd) ? "//$line" :  line.substring(2);
      }).join("\n");
     _upSelectionBlock(body,isAdd? 2:-2);
  }

  final _keyboard = HardwareKeyboard.instance;
  Duration get timeStamp => Duration(milliseconds:  DateTime.now().millisecondsSinceEpoch);
  // 通用方法：发送单个按键事件（无修饰符）
  void sendKeyEvent({
    required LogicalKeyboardKey logicalKey,
    required PhysicalKeyboardKey physicalKey,
  }) {
  //  // 发送按下事件
  //   _keyboard.handleKeyEvent(KeyDownEvent(
  //     logicalKey: logicalKey,
  //     physicalKey: physicalKey,
  //     character: logicalKey.keyLabel, 
  //     timeStamp: timeStamp,
  //   ));
    
  //   // 发送释放事件（完整模拟一次按键）
  //   _keyboard.handleKeyEvent(KeyUpEvent(
  //     logicalKey: logicalKey,
  //     physicalKey: physicalKey,
  //     // character: logicalKey.keyLabel,
  //     timeStamp: timeStamp,
  //   ));

    var keyDownEvent = Event_KeyDown(
        logicalKey: logicalKey,
        physicalKey: physicalKey,
    );
    //  手动触发焦点节点的onKey回调
    self.onKeyDown(keyDownEvent);
  }

  // 通用方法：发送带修饰符的按键事件（Ctrl/Shift等）
  void sendKeyEventWithModifiers({
    required LogicalKeyboardKey logicalKey,
    required PhysicalKeyboardKey physicalKey,
    bool withCtrl = false,
    bool withShift = false,
  }) {
    // 1. 先按下修饰键（Ctrl/Shift）
    if (withCtrl) {
      _keyboard.handleKeyEvent(KeyDownEvent(
        logicalKey: LogicalKeyboardKey.controlLeft,
        physicalKey: PhysicalKeyboardKey.controlLeft, timeStamp: timeStamp,
        synthesized:true,
      ));
    }
    if (withShift) {
      _keyboard.handleKeyEvent(KeyDownEvent(
        logicalKey: LogicalKeyboardKey.shiftLeft,
        physicalKey: PhysicalKeyboardKey.shiftLeft, timeStamp: timeStamp,
        synthesized:true,
      ));
    }

    // 2. 发送主按键事件
    _keyboard.handleKeyEvent(KeyDownEvent(
      logicalKey: logicalKey,
      physicalKey: physicalKey,
      synthesized:true,
      character: logicalKey.keyLabel, timeStamp: timeStamp,
    ));
    _keyboard.handleKeyEvent(KeyUpEvent(
      logicalKey: logicalKey,
      physicalKey: physicalKey,
      synthesized:true,
      timeStamp: timeStamp,
    ));

    // 3. 释放修饰键（与按下顺序相反，避免冲突）
    if (withShift) {
      _keyboard.handleKeyEvent(KeyUpEvent(
        logicalKey: LogicalKeyboardKey.shiftLeft,
        physicalKey: PhysicalKeyboardKey.shiftLeft, timeStamp: timeStamp,
        synthesized:true,
      ));
    }
    if (withCtrl) {
      _keyboard.handleKeyEvent(KeyUpEvent(
        logicalKey: LogicalKeyboardKey.controlLeft,
        physicalKey: PhysicalKeyboardKey.controlLeft, timeStamp: timeStamp,
        synthesized:true,
      ));
    }
    
    List<ModifierKey> metaState = [];
    if (withCtrl) {
      metaState.add(ModifierKey.controlModifier);
    }
    if (withShift) {
      metaState.add(ModifierKey.shiftModifier);
    }
    var keyDownEvent = Event_KeyDown(
        logicalKey: logicalKey,
        physicalKey: physicalKey,
        modifiers: metaState
    );
    //手动触发焦点节点的onKey回调
    self.onKeyDown(keyDownEvent);
  }

  void delLine(){
      var rows = _data.split("\n");
      for (var i in self.cursorLines.reversed) {
        rows.removeAt(i);
      }
      var newText = rows.join("\n");
      // 更新文本和光标位置
      self.controller.value = TextEditingValue(
        text: newText,
        selection: self.controller.selection,
      );
  }
  _toPos(int pos){
    self.controller.selection = TextSelection(
        baseOffset:  pos, extentOffset: pos,
     );
  }
  get _pos => self.controller.selection.baseOffset;
  String get _data => self.controller.text; 
  toLineStart(){
     _toPos(_pos-_data.substring(0,_pos).split("\n").last.length);
  }
  toLineEnd(){
    _toPos(_pos+_data.substring(_pos).split("\n").first.length);
  }

  undo(){
      // 发送撤销指令（模拟系统键盘撤销）
      // ServicesBinding.instance.sendAction(
      //   const Intent(LogicalKeyboardKey.keyZ, isControlPressed: true),
      //   null,
      //   null,
      // );  
  }
}
